/**
 * 通用js方法封装处理
 * Copyright (c) 2019 ruoyi
 */
const baseURL = process.env.VUE_APP_BASE_API

import dayjs from 'dayjs'
import weekOfYear from 'dayjs/plugin/weekOfYear'
dayjs.extend(weekOfYear)

// 时间格式化
export function parseTime(time, pattern) {
	if (arguments.length === 0 || !time) {
		return null
  }
  // {y}-{m}-{d} {h}:{i}:{s}
	const format = pattern || '{y}-{m}-{d}'
	let date
	if (typeof time === 'object') {
		date = time
	} else {
		if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
			time = parseInt(time)
		} else if ((typeof time === 'string') && time.indexOf('T') !== -1) {
      time = renderTime(time)
    } else if (typeof time === 'string') {
			time = time.replace(new RegExp(/-/gm), '/')
		}
		if ((typeof time === 'number') && (time.toString().length === 10)) {
			time = time * 1000
    }

    date = new Date(time)
	}
	const formatObj = {
		y: date.getFullYear(),
		m: date.getMonth() + 1,
		d: date.getDate(),
		h: date.getHours(),
		i: date.getMinutes(),
		s: date.getSeconds(),
		a: date.getDay()
	}
	const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
		let value = formatObj[key]
		// Note: getDay() returns 0 on Sunday
		if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
		if (result.length > 0 && value < 10) {
			value = '0' + value
		}
		return value || 0
	})
	return time_str
}

export function calcTime(startTime, endTime) {
  var start = new Date(startTime).getTime()
  var end = new Date(endTime).getTime()
  var timestamp = end - start
  // 天
  var days = Math.floor(timestamp / (24 * 60 * 60 * 1000))
  // 小时
  var hours = Math.floor((timestamp % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000))
  // 分钟
  var minutes = Math.floor(((timestamp % (24 * 60 * 60 * 1000)) % (60 * 60 * 1000)) / (60 * 1000))
  // 秒
  var second = Math.floor((((timestamp % (24 * 60 * 60 * 1000)) % (60 * 60 * 1000)) % (60 * 1000)) / 1000)

  console.log(days, hours, minutes, second)

  if (days <= 0 && hours <= 0 && minutes <= 0) {
    return second + '秒'
  }

  if (days <= 0 && hours <= 0) {
    return minutes + '分钟'
  }

  if (days <= 0) {
    if (minutes <= 0) {
      return hours + '小时'
    }
    return hours + '小时' + minutes + '分钟'
  }
  return days + '天' + hours + '小时' + minutes + '分钟'
}

export function getWeek(date) {
  var d = new Date(date)
  var day = d.getDay()
  var weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  return weekArr[day]
}

// 2020-05-14T16:27:34.000+0800
export function renderTime(time) {
  time = time.replace('T', ' ')
  const number = time.indexOf('.')
  if (number !== -1) {
    time = time.substring(0, number)
  }
  return time.replace(/-/g, '/')
}

// 表单重置
export function resetForm(refName) {
	if (this.$refs[refName]) {
		this.$refs[refName].resetFields()
	}
}
// 必填定位
export function locationError(document) {
	setTimeout(() => {
    var isError = document.getElementsByClassName('is-error')
    // console.log(isError)
    if (isError[0].querySelector('input')) {
      isError[0].querySelector('input').focus()
    }
    if (isError[0].querySelector('textarea')) {
      isError[0].querySelector('textarea').focus()
    }

    isError[0].scrollIntoView({ block: 'center', behavior: 'smooth' })
  }, 1)
  return false
}

// 添加日期范围
export function addDateRange(params, dateRange) {
	var search = params
	if (dateRange && dateRange.length > 0 && dateRange[0] && dateRange[1]) {
    search.beginTime = this.dateRange === undefined ? dateRange[0] : this.dateRange[0]
    search.endTime = this.dateRange === undefined ? dateRange[1] : this.dateRange[1]
	} else {
    search.beginTime = undefined
    search.endTime = undefined
  }
	return search
}

// 回显数据字典
export function selectDictLabel(datas, value) {
  if (datas) {
    var actions = []
    Object.keys(datas).map((key) => {
      if (datas[key].dictValue === ('' + value)) {
        actions.push(this.$t(datas[key].dictLabel))
        return false
      }
    })
    return actions.join('')
  }
}

// 回显数据字典(可指定匹配key和回显key)
export function selectDictLabelByCustomKey(datas, value, dictValueKey, dictLabelKey) {
  if (datas) {
    var actions = []
    Object.keys(datas).map((key) => {
      if (datas[key][dictValueKey] === ('' + value)) {
        actions.push(this.$t(datas[key][dictLabelKey]))
        return false
      }
    })
    return actions.join('')
  }
}

// 回显数据字典
export function selectDictLabels(datas, value) {
  var actions = []
  if (value !== null && value !== undefined) {
    Object.keys(datas).map((key) => {
      for (var i = 0; i < value.length; i++) {
        if (datas[key].dictValue === ('' + value[i])) {
          if (actions.length > 0) {
            actions.push(',' + datas[key].dictLabel)
          } else {
            actions.push(datas[key].dictLabel)
          }
          return false
        }
      }
    })
  }
  return actions.join('')
}

// 通用下载方法
export function download(fileName) {
	window.location.href = baseURL + '/common/download?fileName=' + encodeURI(fileName) + '&delete=' + true
}

// 字符串格式化(%s )
export function sprintf(str) {
	var args = arguments; var flag = true; var i = 1
	str = str.replace(/%s/g, function() {
		var arg = args[i++]
		if (typeof arg === 'undefined') {
			flag = false
			return ''
		}
		return arg
	})
	return flag ? str : ''
}

// 转换字符串，undefined,null等转化为""
export function praseStrEmpty(str) {
    if (!str || str === 'undefined' || str === 'null') {
        return ''
    }
    return str
}

/**
 * 金额格式化单位
 * @param number
 * @returns {string}
 */
export const moneyFormatUnit = (number, unit) => {
  var val = +(parseFloat(number)).toFixed()
  if (unit === 'W') {
    val = val / 10000
  } else if (unit === 'm') {
    val = val / 1000000
  }
  return (val).toLocaleString()
}

/**
 * @description 格式化金额
 * @param number：要格式化的数字
 * @param val：单位w
 * @param fixed：保留小位数
 * @param mandatorty：是否强制保留
 */

export const moneyFormat = (number, unit, fixed, mandatorty) => {
  const unitVal = window.i18n.t('金额单位')
  if (number === '' || number === null || number === undefined) {
    return ''
  }

  let val = 0
  if (unit === 'rate') {
    // 强制保留4位小数
    val = +(parseFloat(number)).toFixed((fixed || 4))
  } else {
    val = +(parseFloat(number)).toFixed(fixed || 2)
  }
  if (unit === 'w' && (unitVal === '(万)' || unitVal === '（万）' || unitVal === '(万元)' || unitVal === '（万元）')) {
    return mandatorty ? decimalFormat(val, unit, unitVal, fixed, mandatorty) : decimalFormat(val, unit, unitVal, fixed, mandatorty).replace(/0+$/, '').replace(/\.$/, '')
  } else if (unit === 'y' && (unitVal === '(亿)' || unitVal === '（亿）')) {
    return mandatorty ? decimalFormat(val, unit, unitVal, fixed, mandatorty) : decimalFormat(val, unit, unitVal, fixed, mandatorty).replace(/0+$/, '').replace(/\.$/, '')
  } else {
    return mandatorty ? decimalFormat(val, unit, unitVal, fixed, mandatorty) : decimalFormat(val, unit, unitVal, fixed, mandatorty).replace(/0+$/, '').replace(/\.$/, '')
  }
}

export function decimalFormat(value, unit, unitVal, fixed) {
  // 强制保留4位小数
  if (unit === 'rate') {
    return value.toLocaleString('zh', { minimumFractionDigits: fixed || 4, maximumFractionDigits: fixed || 4 })
  }
  if (unit === 'w' && (unitVal === '(万)' || unitVal === '（万）' || unitVal === '(万元)' || unitVal === '（万元）')) {
    return (value / 10000).toLocaleString('zh', { minimumFractionDigits: fixed || 6, maximumFractionDigits: fixed || 6 })
  } else if (unit === 'y' && (unitVal === '(亿)' || unitVal === '（亿）')) {
    return (value / 10000).toLocaleString('zh', { minimumFractionDigits: fixed || 6, maximumFractionDigits: fixed || 6 })
  } else {
    return value.toLocaleString('zh', { minimumFractionDigits: fixed || 2, maximumFractionDigits: fixed || 2 })
  }
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export function handleTree(data, id, parentId, children) {
  var config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children'
  }

  var childrenListMap = {}
  var nodeIds = {}
  var tree = []

  for (var d of data) {
    var parentId2 = d[config.parentId]
    if (childrenListMap[parentId2] == null) {
      childrenListMap[parentId2] = []
    }
    nodeIds[d[config.id]] = d
    childrenListMap[parentId2].push(d)
  }

  for (var d2 of data) {
    var parentId3 = d[config.parentId]
    if (nodeIds[parentId3] == null) {
      tree.push(d2)
    }
  }

  for (var t of tree) {
    adaptToChildrenList(t)
  }

  function adaptToChildrenList(o) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]]
    }
    if (o[config.childrenList]) {
      for (var c of o[config.childrenList]) {
        adaptToChildrenList(c)
      }
    }
  }
  return tree
}

/**
 * ruoyiFloat 包含加减乘除四个方法，能确保浮点数运算不丢失精度
 *
 * 精度丢失问题（或称舍入误差，其根本原因是二进制和实现位数限制有些数无法有限表示
 * 以下是十进制小数对应的二进制表示
 *      0.1 >> 0.0001 1001 1001 1001…（1001无限循环）
 *      0.2 >> 0.0011 0011 0011 0011…（0011无限循环）
 * 计算机里每种数据类型的存储是一个有限宽度，比如 JavaScript
 *  使用 64 位存储数字类型，因此超出的会舍去。舍去的部分就是精度丢失的部分。
 *
 * ** method **
 *  add / subtract / multiply /divide
 *
 * ** explame **
 *  0.1 + 0.2 == 0.30000000000000004 （多了 0.00000000000004）
 *  0.2 + 0.4 == 0.6000000000000001  （多了 0.0000000000001）
 *  19.9 * 100 == 1989.9999999999998 （少了 0.0000000000002）
 *
 * ruoyiFloat.add(0.1, 0.2) === 0.3
 * ruoyiFloat.multiply(19.9, 100) === 1990
 *
 * @returns {{add: (function(*, *): *|number), formatNum: (function(*): *|number), subtract: (function(*, *): *|number), divide: (function(*, *): *|number), multiply: (function(*, *): *|number)}}
 */
export function ruoyiFloat() {
  /*
   * 判断obj是否为一个整数 整数取整后还是等于自己。利用这个特性来判断是否是整数
   */
  function isInteger(obj) {
    // 或者使用 Number.isInteger()
    return Math.floor(obj) === obj
  }

  /*
   * 将一个浮点数转成整数，返回整数和倍数。如 3.14 >> 314，倍数是 100
   * @param floatNum {number} 小数
   * @return {object}
   *   {times:100, num: 314}
   */
  function toInteger(floatNum) {
    // 初始化数字与精度 times精度倍数  num转化后的整数
    var ret = { times: 1, num: 0 }
    // 是否是小数
    var isNegative = floatNum < 0
    // 是否是整数
    if (isInteger(floatNum)) {
      ret.num = floatNum
      // 是整数直接返回
      return ret
    }
    // 转换为字符串
    var strfi = floatNum + ''
    var dotPos = strfi.indexOf('.')
    // 拿到小数点之后的位数
    var len = strfi.substr(dotPos + 1).length
    // 精度倍数
    var times = Math.pow(10, len)
    /* 为什么加0.5?
        前面讲过乘法也会出现精度问题
        假设传入0.16344556此时倍数为100000000
        Math.abs(0.16344556) * 100000000=0.16344556*10000000=1634455.5999999999
        少了0.0000000001
        加上0.5 0.16344556*10000000+0.5=1634456.0999999999 parseInt之后乘法的精度问题得以矫正
    */
    var intNum = parseInt(Math.abs(floatNum) * times + 0.5, 10)
    ret.times = times
    if (isNegative) {
      intNum = -intNum
    }
    ret.num = intNum
    return ret
  }

  /*
   * 核心方法，实现加减乘除运算，确保不丢失精度
   * 思路：把小数放大为整数（乘），进行算术运算，再缩小为小数（除）
   * @param a {number} 运算数1
   * @param b {number} 运算数2
   */
  function operation(a, b, op) {
    var o1 = toInteger(a)
    var o2 = toInteger(b)
    var n1 = o1.num
    var n2 = o2.num
    var t1 = o1.times
    var t2 = o2.times
    var max = t1 > t2 ? t1 : t2
    var result = null
    switch (op) {
      // 加减需要根据倍数关系来处理
      case 'add':
        // 两个小数倍数相同
        if (t1 === t2) {
          result = n1 + n2
        } else if (t1 > t2) {
          // o1 小数位 大于 o2
          result = n1 + n2 * (t1 / t2)
        } else {
          // o1小数位小于 o2
          result = n1 * (t2 / t1) + n2
        }
        return result / max
      case 'subtract':
        if (t1 === t2) {
          result = n1 - n2
        } else if (t1 > t2) {
          result = n1 - n2 * (t1 / t2)
        } else {
          result = n1 * (t2 / t1) - n2
        }
        return result / max
      case 'multiply':
        // 325*3153/(100*1000) 扩大100倍 ==>缩小100倍
        result = (n1 * n2) / (t1 * t2)
        return result
      case 'divide':
        // (325/3153)*(1000/100)  缩小100倍 ==>扩大100倍
        result = (n1 / n2) * (t2 / t1)
        return result
    }
  }

  // 加减乘除的四个接口
  function add(a, b) {
    return operation(a, b, 'add')
  }

  function subtract(a, b) {
    return operation(a, b, 'subtract')
  }

  function multiply(a, b) {
    return operation(a, b, 'multiply')
  }

  function divide(a, b) {
    return operation(a, b, 'divide')
  }

  // 单一数值保持精度
  function formatNum(a) {
    return operation(a, 0, 'add')
  }

  return {
    add: add,
    subtract: subtract,
    multiply: multiply,
    divide: divide,
    formatNum: formatNum
  }
}

/** 格式化金额, 保留精度及小数 **/
export function decimalNum(num) {
  if (num === null || num === undefined || isNaN(num)) {
    num = 0
  }
  return ruoyiFloat().formatNum(Number(num).toFixed(4))
}

/**
 * 校验为空
 * @param val
 * @returns {boolean}
 */
export function isEmpty(val) {
  return val === undefined || val === null || val === '' || val.length <= 0
}

export function getWeekDescription(targetDate) {
  var _day = new Date()
  this.weekNumber = getWeekNumber(_day)
  if (targetDate) {
    var week = getWeekNumber(targetDate)
    // console.log(this.weekNumber, week)
    var date = new Date(targetDate)
    var year = date.getFullYear()
    if (this.weekNumber - week === 1) {
      return '上周'
    } else if (week - this.weekNumber === 1) {
      return '下周'
    } else if (this.weekNumber === week) {
      return '本周'
    } else {
      return year + '年第' + week + '周'
    }
  }
}

export function getWeekNumber(day) {
  var date = day.getDay()
  var week = dayjs(day).week()
  return date === 0 ? week - 1 : week
}
/**
 * 从连接或表单中获取业务ID
 * @Param queryId   取自: this.$route.query.id
 * @Param form      如果上面没有, 就从form表单里取
 */
export function autoBusinessId(queryId, form) {
  if (!isEmpty(queryId)) {
    return queryId
  } else {
    form = isEmpty(form) ? {} : form
    if (!isEmpty(form.fundId)) {
      return form.fundId
    } else if (!isEmpty(form.dealId)) {
      return form.dealId
    } else {
      return undefined
    }
  }
}

function formatMoney(value) {
  if (value) {
    if (!isNaN(value)) {
      return parseFloat(value).toFixed(2)
    } else {
      return value
    }
  } else {
    return '0.00'
  }
}

/**
 * 金额增加千分位
 * @param {*} val
 * @returns
 */
export function formattedNumber(val) {
  val = formatMoney(val)
  if (val != null && !isNaN(Number(val))) {
    if (typeof val === 'string') {
      return parseFloat(val).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    } else if (typeof val === 'number') {
      return val.toLocaleString('en-US', {
        style: 'decimal',
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      })
    }
  } else {
    return val
  }
}

// 回显请求来的列表数据
export function selectListLabel(datas, value, ListLabel, ListValue) {
  // console.log(datas, value, ListLabel, ListValue)
  var actions = []
  if (datas instanceof Array) {
    if (value instanceof Array) {
      Object.keys(datas).map((key) => {
        for (var i = 0; i < value.length; i++) {
          if (datas[key][ListValue] === ('' + value[i])) {
            if (actions.length > 0) {
              actions.push(',' + datas[key][ListLabel])
            } else {
              actions.push(datas[key][ListLabel])
            }
            return false
          }
        }
      })
    } else {
      Object.keys(datas).map((key) => {
        if (datas[key][ListValue] === ('' + value)) {
          actions.push(this.$t(datas[key][ListLabel]))
          return false
        }
      })
    }
    return actions.join('')
  } else {
    return ''
  }
}
